//TOS_NODE_ID options
//0 = Temp sensor
//1 = serial interface
//2 = vent controller

module AC2P
{
	uses interface Boot;
	uses interface Timer<TMilli> as TempTimer;
	uses interface Timer<TMilli> as SerialTimer;
	uses interface Leds;
	uses interface AMSend as RadioSend;
	uses interface AMSend as SerialSend;
	uses interface Receive;
	uses interface Packet as RadioPacket;
    uses interface Packet as SerialPacket;
	uses interface SplitControl as RadioControl;
    uses interface SplitControl as SerialControl;
	uses interface Read<uint16_t>;
}
implementation
{
	uint16_t lastReading;
	uint16_t storeReading;
	message_t buffer;
	uint8_t epsilon;
	uint16_t targetTemp;
	uint8_t ledSetting;
	uint8_t counter = 0;
	bool parseBusy;
	bool WAIT_FOR_OPEN = TRUE;
	bool WAIT_FOR_CLOSE = TRUE;

	
	event void Boot.booted()
	{
		parseBusy = 0;
		if(call RadioControl.start() != SUCCESS)
			call Leds.set(7);

        if (call SerialControl.start() != SUCCESS)
            call Leds.set(7);
	}
	
    // Occurs when the radio control start has completed
	event void RadioControl.startDone(error_t err)
	{
		if(err != SUCCESS)
			call Leds.set(7);
		else
		{
			if(TOS_NODE_ID == 0)
				call TempTimer.startPeriodic(100);		
		}
	}
	
    // Nothing done here
	event void RadioControl.stopDone(error_t err) { }

    // Occurs when the serial control start has completed
    event void SerialControl.startDone(error_t err)
    {
        if (err != SUCCESS)
        {
            call Leds.set(7);
        }
        else
        {
            if (TOS_NODE_ID == 1 || TOS_NODE_ID == 2)
            	call SerialTimer.startPeriodic(1024);
        }
    }

    // Nothing done here
    event void SerialControl.stopDone(error_t err) { }

    // Display all LEDs on error
    event void SerialSend.sendDone(message_t* msg, error_t err)
    {
        if (err != SUCCESS) call Leds.set(7);
    }
	
	task void handleTempTimer();
	task void handleReading();
	task void handleSerialTimer();
	task void parsePacket();
	
	event void TempTimer.fired()
	{
		post handleTempTimer();
	}

    // Take a reading from the thermometer
	task void handleTempTimer()
	{
        // If fails, try again
		if(call Read.read() != SUCCESS)
			post handleTempTimer();
	}

    event void SerialTimer.fired()
    {
        post handleSerialTimer();
    }
	
    // Creates a serial packet, sets the last reading, then sends it out the serial port
    task void handleSerialTimer()
    {
        serial_msg_t* payload = (serial_msg_t*)call SerialPacket.getPayload(&buffer, sizeof(serial_msg_t));

		counter ++;
        payload->message = lastReading;
		//payload->nodeid = TOS_NODE_ID;
		payload->counter = message_id;

		if (TOS_NODE_ID == 1) {
			ledSetting ^= 0x01;
        	call Leds.set(ledSetting);
        }
        
        if (call SerialSend.send(AM_SERIAL_MSG, &buffer, sizeof(serial_msg_t)) != SUCCESS)
        {
            call Leds.set(7);
            post handleSerialTimer();
        }  
    }
	
    // Occurs when the temperature reading is done
	event void Read.readDone(error_t err, uint16_t val)
	{
		if(err != SUCCESS)
			post handleTempTimer();
		else
		{
			ledSetting ^= 0x02;
			call Leds.set(ledSetting);
			lastReading = val;
			post handleReading();
		}
	}
	
    // Write the reading to the network
	task void handleReading()
	{
		ac2_msg_t * payload = (ac2_msg_t *)call RadioPacket.getPayload(&buffer, sizeof(ac2_msg_t));
		
		//counter ++;
        //payload->message = lastReading;
		//payload->nodeid = TOS_NODE_ID;
		//payload->counter = counter;
		payload->reading = lastReading;

        //call Leds.set(payload->reading % 8);
		
		if(call RadioSend.send(AM_BROADCAST_ADDR, &buffer, sizeof(ac2_msg_t)) != SUCCESS) {
			post handleReading();
		}
	}
	
	event void RadioSend.sendDone(message_t * msg, error_t err)
	{
		if(err != SUCCESS)
			post handleReading();
	}
	
	event message_t * Receive.receive(message_t * msg, void * payload, uint8_t len)
	{
		ac2_msg_t * ac2_payload = (ac2_msg_t *)payload;

        lastReading = ac2_payload->reading;
		
		//if (!parseBusy) {
		//	parseBusy = 1;
			storeReading = lastReading;
		//}
		
		post parsePacket();
		
		return msg;
	}
	
	task void parsePacket() {
		if (TOS_NODE_ID == 2) {
			//ledSetting ^= 0x4;
			//call Leds.set(ledSetting);
		
	
			epsilon = 0x20;
			targetTemp = 0x1C00;
		
			//blink the blue LED
			ledSetting ^= 0x04;
		
			//if hotter than target, turn on green light
			if (storeReading > targetTemp + epsilon  && WAIT_FOR_OPEN) {
				//ledSetting &= 0x01;
				WAIT_FOR_CLOSE = TRUE;
			    WAIT_FOR_OPEN = FALSE;
			    //turn off Close LED
				ledSetting &= 0xFE;
				//turn on Open LED
				ledSetting |= 0x02;
			}
		
			//if cooler than target, turn on red light
			if (storeReading < targetTemp - epsilon && WAIT_FOR_CLOSE) {
			    //ledSetting &= 0x02;
			    WAIT_FOR_CLOSE = FALSE;
			    WAIT_FOR_OPEN = TRUE;
			    //turn off Open LED
			    ledSetting &= 0xFD;
			    //turn on Close LED
			    ledSetting |= 0x01;
			}
		
			call Leds.set(ledSetting);
		}
		parseBusy = 0;
	}
}
